function [NumSamples, NumSeries, NumParams] = ...
	checkmvnrsetup(Data, Design, Param, Covar, IgnoreNaNs)
%CHECKMVNRSETUP Private routine to check problem formulation and obtain dims.
% Check inputs to multivariate normal regression and least-squares regression
% routines to ensure proper formats. Data is a NUMSAMPLES x NUMSERIES
% matrix and Design is either a NUMSAMPLES x NUMPARAMS matrix if NUMSERIES = 1
% or a cell array with either 1 or NUMSAMPLES cells with NUMSERIES x NUMPARAMS
% matrices. Optional inputs are Param, Covar, and IgnoreNaNs.
%
%	[NumSamples, NumSeries, NumParams] = checkmvnrsetup(Data, Design);
%	[NumSamples, NumSeries, NumParams] = ...
%		checkmvnrsetup(Data, Design, Param, Covar, IgnoreNaNs);
%
% Inputs:
%	Data - NUMSAMPLES x NUMSERIES matrix with NUMSAMPLES samples of a
%		NUMSERIES-dimensional random vector. If values are missing, they are
%		represented as NaNs. This routine ignores entire samples if any series
%		within a sample has a NaN value.
%	Design - Either a matrix or a cell-array to handle two distinct model
%		structures. First, if NUMSERIES = 1, Design can be a NUMSAMPLES x
%		NUMPARAMS matrix with known values. This is the "standard" form for
%		regression on a single data series. Alternatively, for any NUMSERIES
%		>= 1, Design can be a cell array of either 1 or NUMSAMPLES cells, where
%		each cell contains a NUMSERIES x NUMPARAMS matrix of known values. If
%		Design has a single cell, then it is assumed to be the same Design
%		matrix for each sample. Otherwise, Design must contain individual
%		Design matrices for each sample.
%
% Optional Inputs:
%	Param - NUMPARAMS x 1 column vector of estimates for the parameters of the
%		regression model.
%	Covar - NUMSERIES x NUMSERIES matrix of estimates for the covariance of the
%		residuals of the regression.
%	IgnoreNaNs - Boolean flag set to true if NaN values in data are to be
%		ignored and false otherwise. Default is false.
%
% Outputs:
%	NumSamples - Number of independent samples. This quantity is derived from
%		the input Data matrix.
%	NumSeries - Number of series within each sample. This quantity is derived
%		from the input Data matrix.
%	NumParams - Number of model parameters to be estimated. This quantity is
%		derived from the input Design array.
%
% Notes:
%	Whereas NaN values are permitted in the Design arrays if and only if they do
%	not conflict with missing values in Data, if Design is a 1 x 1 cell array
%	with a single design matrix to be used for each sample, it cannot have any
%	NaNs.

%	Copyright 2005 The MathWorks, Inc.
%	$Revision: 1.1.6.2 $ $Date: 2007/06/04 21:07:33 $

if nargin < 5
	IgnoreNaNs = false;
end
if nargin < 4
	Covar = [];
end
if nargin < 3
	Param = [];
end
if (nargin < 2)
	error('Finance:checkmvnrsetup:MissingInputArg', ...
		'Missing required arguments Data or Design.');
end

if isempty(Data)
	error('Finance:checkmvnrsetup:EmptyDataArray', ...
		'Data array is empty - cannot continue.');
end

if isempty(Design)
	error('Finance:checkmvnrsetup:EmptyDesignArray', ...
		'Design array is empty - cannot continue.');
end

[NumSamples, NumSeries] = size(Data);

if iscell(Design)
	Design = Design(:);
	[m, n] = size(Design);
	
	if m == 1
		SingleDesign = true;
	elseif m == NumSamples
		SingleDesign = false;
	else
		error('Finance:checkmvnrsetup:InconsistentDims', ...
			'Invalid number of cell array elements - should be either NumSamples or 1.');
	end
		
	if isempty(Design{1})
		error('Finance:checkmvnrsetup:InvalidDesignArray', ...
			'Empty Design{1} cell array element - unable to continue.');
	end
	
	[n, NumParams] = size(Design{1});
	
	if n ~= NumSeries
		error('Finance:checkmvnrsetup:InconsistentDims', ...
			'Invalid number of series in cell array elements (should be NumSeries).');
	end

	if ~SingleDesign
		for k = 1:NumSamples
			if isempty(Design{k})
				error('Finance:checkmvnrsetup:InvalidDesignArray', ...
					'Empty Design{%d} cell array element.',k);
			end
			if ~all(isequal(size(Design{k}), [NumSeries, NumParams]))
				error('Finance:checkmvnrsetup:InconsistentDims', ...
					'Invalid dimensions for Design{%d} cell array element (should be NumSeries x NumSamples).',k);
			end
		end
	end
else
	[n, NumParams] = size(Design);

	if n ~= NumSamples
		error('Finance:checkmvnrsetup:InconsistentDims', ...
			'Invalid format or dimensions for Design matrix (should be NumSamples x NumParams).');
	end
end

if any(sum(isnan(Data),1) == NumSamples)
	error('Finance:checkmvnrsetup:TooManyNaNs', ...
		'One or more data series has all NaNs.');
end

if any(any(isinf(Data)))
	error('Finance:checkmvnrsetup:InfiniteValue', ...
		'One or more infinite values found in Data.');
end

if iscell(Design)
	if SingleDesign
		if any(any(isnan(Design{1})))
			error('Finance:checkmvnrsetup:InvalidDesign', ...
				'Cell array with single Design{1} matrix cannot have missing values.');
		end

		if any(any(isinf(Design{1})))
			error('Finance:checkmvnrsetup:InfiniteValue', ...
				'One or more infinite values found in cell array with single Design{1} matrix.');
		end
		
		r = rank(Design{1});
		if (NumSeries < NumParams) || (r ~= NumParams)
			error('Finance:checkmvnrsetup:InvalidDesignArray', ...
				'Cell array with single Design{1} matrix has rank-deficient matrix.');	
		end
	else
		for k = 1:NumSamples
			if IgnoreNaNs
				if ~any(isnan(Data(k,:))) && any(any(isnan(Design{k})))
					error('Finance:checkmvnrsetup:InvalidDesign', ...
						'Cell array Design{%d} matrix cannot have missing values whenever data is not missing.',k);
				end
			else
				if ~all(isnan(Data(k,:))) && any(any(isnan(Design{k})))
					error('Finance:checkmvnrsetup:InvalidDesign', ...
						'Cell array Design(%d) matrix cannot have missing values whenever data is not ignored.',k);
				end
			end
		
			if any(any(isinf(Design{k})))
				error('Finance:checkmvnrsetup:InfiniteValue', ...
					'One or more infinite values found in cell array Design(%d) matrix.',k);
			end
		end
	end
else
	for k = 1:NumSamples
		if ~isnan(Data(k,1)) && any(isnan(Design(k,:)))
			error('Finance:checkmvnrsetup:InvalidDesign', ...
				'Design matrix cannot have missing values whenever data is not missing.');
		end
		if any(any(isinf(Design(k))))
			error('Finance:checkmvnrsetup:InfiniteValue', ...
				'One or more infinite values found in Design matrix.');
		end
	end
end

if ~isempty(Param) && ~all(isequal(size(Param), [NumParams, 1]))
	error('Finance:checkmvnrsetup:InconsistentDims', ...
		'Invalid dimensions for model parameter vector (should be %d x 1).',NumParams);
end

if ~isempty(Covar) && ~all(isequal(size(Covar), [NumSeries, NumSeries]))
	error('Finance:checkmvnrsetup:InconsistentDims', ...
		'Invalid dimensions for covariance or weight matrix (should be %d x %d).', ...
		NumSeries, NumSeries);
end
